#!/bin/bash
# This script installs helm on a Linux machine.
# supports installation on both Ubuntu and CentOS operating systems
# Usage: ./install.sh [--online|-o] [--force|-f] [--version=<version>] [--group=<group>] [--pkg-mirror=<https://xxx>][--image-mirror=<https://xxx>][--rm|--remove] [--clean|-c] [--downloadonly|-d]
# Options:
#   --online|-o: install using online method
#   --force|-f: force installation
#   --version=<version>: specify the version to be installed
#   --rm|--remove: uninstall kubeadm/kubelet/kubectl
#   --clean|-c: remove downloaded files
#   --downloadonly|-d: only download kubeadm/kubelet/kubectl package, do not install
#   example1, download 20.10.20 pkg: 
#           ./install.sh --version=20.10.20 --force --downloadonly
#   example2, install 20.10.20 then clean pkg: 
#          ./install.sh --version=20.10.20 --clean
#   example3, install 20.10.20 using apt or yum, and force installation: 
#          ./install.sh --version=20.10.20 -fo
#   example4, install latest using apt or yum
#          ./install.sh --online, or ./install.sh -o
# Functionality:
# 0. This script supports installation on both Ubuntu and CentOS operating systems.
# 1. Specify the version to be installed TARGET_VERSION and whether to force if FORCE
# 2. Determine whether the local version current_version is >= the specified version TARGET_VERSION. If it is, do not install it. If --force is specified, force installation
# 3. Installation process:
#    1) Uninstall the local version
#    2) Call the official script https://get.docker.com to install the specified version
# 4. Configure group as the specified group, default is root
# 5. Configure the /etc/docker/daemon.json file
# 6. Configure and start the service

# 该脚本在 Linux 机器上安装 helm 组件（kubeadm、kubelet、kubectl）。适用于ubuntu或者centos
# 使用方法: ./install.sh [--force] [--version=<version>] [--group=<group>] [--mirror=<https://xxx>] [--rm|--remove]
# Options:
# 选项:
#   --online|-o: 使用在线方法安装，即使用apt或者yum安装。不指定时，默认为使用二进制包安装，如果没有二进制包，则自动下载。
#   --force|-f: 强制安装
#   --version=<version>: 指定要安装的版本。如果指定的是在线安装，则自动获得最新版本，如果是离线安装，则默认为20.10.24
#   --rm|--remove: 卸载 kubeadm/kubelet/kubectl
#   --clean|-c: 删除已下载的文件，单独指定，则为删除安装包，加上其它flag，则为安装后自动删除安装包
#   --downloadonly|-d: 仅下载 kubeadm/kubelet/kubectl包但不安装
#   示例1，下载20.10.20版本的包: 
#           ./install.sh --version=20.10.20 --force --downloadonly
#   示例2，安装20.10.20版本，然后清理包: 
#          ./install.sh --version=20.10.20 --clean
#   示例3，使用在线方法(apt或者yum)安装20.10.20版本，并强制安装: 
#          ./install.sh --version=20.10.20 -fo
#   示例4，使用apt或者yum安装最新版本
#          ./install.sh --online 或者 ./install.sh -o
TOP_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." &> /dev/null && pwd )"
CUR_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
if [ -f $TOP_DIR/scripts/utils.sh ]; then
    source $TOP_DIR/scripts/utils.sh
else 
    curl -fsSL https://gitee.com/Vivio2x/k8s-install/raw/1.0.2/scripts/utils.sh -o $CUR_DIR/utils.sh
    chmod +x $CUR_DIR/utils.sh
    source $CUR_DIR/utils.sh
fi
if [ -f $TOP_DIR/config/download.yaml ]; then
    create_variables $TOP_DIR/config/download.yaml
fi

#二进制包下载路径
#要求源站的目录下安装包路径格式为http://x/.../x86_64/docker-${version}.tgz
ARCH=$([ "x86_64" == $(uname -m) ] && echo "amd64")
#TARGET_VERSION是可变的，，使用方法，在TARGET_VERSION确定后，执行BINARY_URL_PATH=$(eval echo $BINARY_URL_PATH)
#例如，./install.sh --version=1.21.11, 则url=https://dl.k8s.io/release/v1.21.11/bin/linux/${ARCH}
BINARY_URL_PATH=${DL_helm_bin:-"https://get.helm.sh/helm-v\${TARGET_VERSION}-linux-amd64.tar.gz"}
DOWNLOAD_DIR=$CUR_DIR/package
DEFAULT_VERSION=3.9.4
BIN_DIR=/usr/local/bin


get_default_version() {
    if $ONLINE; then
        echo $(get_latest_version helm)
    else
        echo "$DEFAULT_VERSION"
    fi
}

# Check if helm components are installed and if they need to be upgraded
helm_needs_installation() {
    if [ -x "$(command -v helm)" ]; then
        CURRENT_VERSION=$(helm version --short | grep -oE "$VERSION_REGEX")
        #echo "Current version: $current_version, target version: $TARGET_VERSION"
        if [ -z "$TARGET_VERSION" ] && [ "$FORCE" = "false" ]; then
            echo "Current version is $CURRENT_VERSION, use '--force=true' or '--verion=<version> to install as desired"
			      return 1
        elif check_version_ge "$CURRENT_VERSION" "$TARGET_VERSION" && [ "$FORCE" != "true" ]; then
            echo "Current version ($CURRENT_VERSION) >= target version($TARGET_VERSION), and force=$FORCE; no need to install"
            return 1
        fi
    fi
    return 0
}
# Remove all Docker related files and services
# 删除docker所有的文件
remove_helm() {
    set -x
    rm -rf $BIN_DIR/helm
    set +x
}
# deletes the old version of helm components.
# 删除旧版本的 helm 组件。
delete_old_version() {
    if [ -z "$CURRENT_VERSION" ]; then
        if [ -x "$(command -v helm)" ]; then
            CURRENT_VERSION=$(helm version --short| grep -oE '[0-9]+\.([0-9]+)\.([0-9]+)')
            CURRENT_VERSION=${CURRENT_VERSION#*v}
        else
            echo "helm are not installed"
            #return
        fi
    fi

    echo "Delete version $CURRENT_VERSION ..."
    delete_pkg helm
    clean_locks
    remove_helm
}

# Update package manager
add_repo() {
    echo "add helm repo"
    if [ "$PACKAGE_MANAGER" == "apt-get" ]; then
        curl  -fsSL https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
        sudo apt-get install apt-transport-https --yes
        echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
       # cat > /etc/apt/sources.list.d/helm-stable-debian.list <<-EOF 
#deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main
#EOF
    #elif [ "$PACKAGE_MANAGER" == "yum" ]; then
       
    fi
    if [ "$PACKAGE_MANAGER" == "apt-get" ]; then
        echo "update packages: apt-get update ... "
        apt-get update -y > /dev/null 2>&1
    elif [ "$PACKAGE_MANAGER" == "yum" ]; then
        echo "update packages: yum makecache ... "
        yum makecache -y > /dev/null 2>&1
    fi
}

# install helm online.
# 在线安装 helm 。
install_helm_online() {
    local count=0
    clean_locks
    if [ "$PACKAGE_MANAGER" == "yum" ]; then
      bash -xc "yum install -y helm-v${TARGET_VERSION}"
    elif [ "$PACKAGE_MANAGER" == "apt-get" ]; then
      local version=$(apt-cache madison helm | grep -o "${TARGET_VERSION}[^ \t]*")
      bash -xc "apt-get install -y helm=${version}"
    fi
    hash -r
}

#离线安装，二进制安装
install_helm_offline() {
    if [ ! -d $DOWNLOAD_DIR ]; then
        download_pkg
    fi
    set -x
    tar -zxvf $DOWNLOAD_DIR/$(basename $BINARY_URL_PATH) -C $DOWNLOAD_DIR/
    cp -rf $DOWNLOAD_DIR/linux-amd64/helm $BIN_DIR/
    chmod +x $BIN_DIR/helm
    helm version
    hash -r
    set +x
}

download_pkg() {
    mkdir -p $DOWNLOAD_DIR
    download_url_until_succeed ${BINARY_URL_PATH} $DOWNLOAD_DIR/$(basename $BINARY_URL_PATH)
}


clean_download() {
    bash -xc "rm -rf $DOWNLOAD_DIR"
}
function print_usage() {
    echo "Usage: $0 [--online|-o] [--force|-f] [--version=<version>] [--group=<group>] [--pkg-mirror=<https://xxx>][--image-mirror=<https://xxx>][--rm|--remove] [--clean|-c] [--downloadonly|-d]"
    echo "Options:"
    echo "  --online|-o: install using apt-get or yum(online=true), default install method is using binary(online=false)"
    echo "  --force|-f: force installation, default force=false"
    echo "  --version=<version>: specify the version to be installed, default is latest(online) or 20.10.24(apt/yum)"
    echo "  --group=<group>: specify the group to be configured, default is root"
    echo "  --pkg-mirror=<https://xxx>: specify the pkg mirror to be used, default is https://mirrors.ustc.edu.cn"
    echo "         eg: 1, https://mirrors.ustc.edu.cn"
    echo "             2, https://mirrors.tuna.tsinghua.edu.cn"
    echo "             3, https://mirrors.aliyun.com"
    echo "             4, http://mirrors.163.com"
    echo "             5, http://mirrors.cloud.tencent.com"
    echo "  --rm|--remove: uninstall helm"
    echo "  --clean|-c: remove downloaded files"
    echo "  --downloadonly|-d: only download helm package, do not install"
    echo "  example1, download 1.21.11 binary pkg: "
    echo "          ./install.sh --version=1.21.11 --force --downloadonly"
    echo "  example2, install 20.10.20 using binary pkg, and then clean binary pkg" 
    echo "         ./install.sh --version=1.21.11  --clean"
    echo "  example3, install 20.10.20 using online method(by apt or yum), and force installation:" 
    echo "         ./install.sh --version=1.21.11  -fo"
}

#
#=====================main func ==============================
if [[ $EUID -ne 0 ]]; then
    echo "This script must be run as root"
    exit 1
fi

#清除旧版本的影响，保证command -v命令得到正确的结果
hash -r

ARGS=$#

# Parse command line arguments
while [[ $# -gt 0 ]]
do
    key="$1"
    case $key in
    --online|-o)
        ONLINE=true
        shift
        ;;
    --clean|-c)
        if [[ $ARGS -eq 1 ]]; then
            clean_download
            exit 0
        fi
        AUTOCLEAN=true
        shift
        ;;
    --downloadonly|-d)
        DOWNLOAD_ONLY=true
        shift
        ;;
    --force|-f)
        FORCE=true
        shift
        ;;
    --version)
        shift
        TARGET_VERSION="${key}"
        shift
        ;;
    --version=*)
        TARGET_VERSION="${key#*=}"
        shift
        ;; 
    --help)
        print_usage
        exit 1
        ;;
    --rm|--remove)
        echo "helm components uninstall..."
        delete_old_version
        exit 1
        ;;
    -[^-]*)
        for ((i=1; i<${#key}; i++)); do
          case "${key:$i:1}" in
            o) ONLINE=true ;;
            f) FORCE=true ;;
            c) AUTOCLEAN=true ;;
            d) DOWNLOAD_ONLY=true ;;
            *) print_usage; exit 1 ;;
          esac
        done
        shift    
        ;;
    *)    # unknown option
        print_usage
        exit 1
        ;;
    esac
done

ONLINE=${ONLINE:-false}
PKG_MIRROR=${PKG_MIRROR:-$DEFAULT_PKG_MIRROR}
FORCE=${FORCE:-false}
GROUP=${GROUP:-root}
DOWNLOAD_ONLY=${DOWNLOAD_ONLY:-false}
AUTOCLEAN=${AUTOCLEAN:-false}

#设置软件安装源，从而获得最新版本
$ONLINE && add_repo
TARGET_VERSION=${TARGET_VERSION:-$(get_default_version)}
BINARY_URL_PATH=$(eval echo $BINARY_URL_PATH)


echo "targetVersion=$TARGET_VERSION force=$FORCE online=$ONLINE"
echo "downloadonly=$DOWNLOAD_ONLY group=$GROUP pkg-mirror=$PKG_MIRROR"
if ! $ONLINE; then
    echo "binary package download url=$BINARY_URL_PATH"
fi

if $ONLINE && $DOWNLOAD_ONLY; then
    echo "Err: downloadonly used only in offline mode"
    exit 1
fi
if $DOWNLOAD_ONLY ; then
    download_pkg
    exit 0
fi
# Main script
if helm_needs_installation; then
    [ -n "$CURRENT_VERSION" ] && delete_old_version

    echo "Install version $TARGET_VERSION ..."
    if $ONLINE ; then
        install_helm_online
    else
        install_helm_offline
    fi
    $AUTOCLEAN && clean_download
fi



